package org.example.user.statistic.service.impl;

import org.example.admin.manage.service.SysAdminService;
import org.example.commons.entity.SysAdmin;
import org.example.commons.entity.SysHealthRecord;
import org.example.commons.entity.SysHealthStatus;
import org.example.commons.entity.SysUser;
import org.example.commons.enums.PassResultEnum;
import org.example.commons.utils.UpdateUtil;
import org.example.user.manage.service.ISysUserService;
import org.example.user.statistic.dto.SysHealthRecordDTO;
import org.example.user.statistic.form.HealthRecordSearchForm;
import org.example.user.statistic.repository.SysHealthRecordRepository;
import org.example.user.statistic.service.ISysHealthRecordService;
import org.example.user.manage.service.ISysHealthStatusService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 扫描记录 服务层接口实现
 *
 * @author bothin
 */
@Service
public class SysHealthRecordServiceImpl implements ISysHealthRecordService {
    @Autowired
    private ISysUserService userService;

    @Autowired
    private SysAdminService adminService;

    @Autowired
    private ISysHealthStatusService healthStatusService;

    @Autowired
    private SysHealthRecordRepository repository;

    @Override
    public SysHealthRecordDTO queryById(Long id) {
        return convert(repository.findById(id).orElse(null));
    }

    @Override
    public Page<SysHealthRecordDTO> queryAllPage(Pageable pageable) {
        return convert(repository.findAll(pageable), pageable);
    }

    @Override
    @Transactional
    public SysHealthRecordDTO insert(SysHealthRecordDTO entity) {
        SysHealthRecordDTO healthRecordDTO = convert(repository.save(convert(entity)));
        if (Objects.nonNull(healthRecordDTO)) {
            //插入出入记录成功后，更新住户状态信息
            SysHealthStatus healthStatus = healthStatusService.findByUserId(entity.getUserId());
            if (Objects.isNull(healthStatus)) {
                healthStatus = SysHealthStatus.builder()
                        .userId(entity.getUserId())
                        .healthStatus(entity.getHealthStatus())
                        .accessTimes(0)
                        .temperature(entity.getTemperature())
                        .remarks(entity.getRemarks())
                        .build();
            } else {
                healthStatus.setHealthStatus(entity.getHealthStatus());
                healthStatus.setTemperature(entity.getTemperature());
                healthStatus.setRemarks(entity.getRemarks());
            }
            //如果允许出入，则出入次数加1
            if (entity.getPassResult().equals(PassResultEnum.ALLOW.getCode())) {
                healthStatus.setAccessTimes(healthStatus.getAccessTimes() + 1);
            }
            healthStatusService.save(healthStatus);
        }
        return healthRecordDTO;
    }

    @Override
    @Transactional
    public SysHealthRecordDTO update(SysHealthRecordDTO entity) {
        SysHealthRecord healthRecord = updateInfo(entity);
        SysHealthRecordDTO healthRecordDTO = convert(repository.save(healthRecord));

        return healthRecordDTO;
    }

    @Override
    public void deleteById(Long id) {
        repository.deleteById(id);
    }

    @Override
    public List<SysHealthRecordDTO> findByRecordIdIn(Long[] ids) {
        return repository.findByRecordIdIn(ids).stream().map(this::convert).collect(Collectors.toList());
    }

    @Override
    public List<SysHealthRecordDTO> queryAll() {
        return repository.findAll().stream().map(this::convert).collect(Collectors.toList());
    }

    @Override
    public Page<SysHealthRecordDTO> findByAdminId(Long adminId, Pageable pageable) {
        return convert(repository.findByAdminId(adminId, pageable), pageable);
    }

    @Override
    public Page<SysHealthRecordDTO> findByUserId(Long userId, Pageable pageable) {
        return convert(repository.findByUserId(userId, pageable), pageable);
    }

    @Override
    public Page<SysHealthRecordDTO> searchList(HealthRecordSearchForm form, Pageable pageable) {
        form.setAdminName("%" + form.getAdminName() + "%");
        form.setUserName("%" + form.getUserName() + "%");
        form.setRecordAddress("%" + form.getRecordAddress() + "%");
        return repository.searchList(form, pageable);
    }

    @Override
    public List<SysHealthRecord> queryLastRecordBydays(Integer days) {
        return repository.findLastSysHealthRecords(days);
    }

    @Override
    public List<SysHealthRecord> queryTimeRecordBydays(Integer day1, Integer day2) {
        return repository.findTimeSysHealthRecords(day1,day2);
    }

    @Override
    public   List<Float>  queryLastTimesUser(Long userId, Integer times) {
        return repository.findLastTimesUser(userId,times);
    }

    @Override
    public List<Date> findLastTimesUserRecord(Long userId, Integer times) {
        return repository.findLastTimesUserRecord(userId,times);
    }

    @Override
    public Float findTimeAvgTemperature(Integer day1, Integer day2) {
         if(repository.findTimeAvgTemperature(day1,day2)==null) return Float.valueOf(0);
        return repository.findTimeAvgTemperature(day1,day2);
    }

    @Override
    public Long findTimeSum(Integer day1, Integer day2) {
        return repository.findTimeSum(day1,day2);
    }

    private SysHealthRecord convert(SysHealthRecordDTO recordDTO) {
        if (recordDTO == null) return null;
        SysHealthRecord sysHealthRecord = new SysHealthRecord();
        BeanUtils.copyProperties(recordDTO, sysHealthRecord);
        return sysHealthRecord;
    }

    private SysHealthRecordDTO convert(SysHealthRecord record) {
        if (record == null) return null;
        SysHealthRecordDTO sysHealthRecordDTO = new SysHealthRecordDTO();
        BeanUtils.copyProperties(record, sysHealthRecordDTO);
        if (record.getUserId() != null) {
            SysUser sysUser = userService.queryById(record.getUserId());
            if (sysUser != null)
                sysHealthRecordDTO.setUserName(sysUser.getName());
        }
        if (record.getAdminId() != null) {
            SysAdmin sysAdmin = adminService.queryById(record.getAdminId());
            if (sysAdmin != null)
                sysHealthRecordDTO.setAdminName(sysAdmin.getName());
        }
        return sysHealthRecordDTO;
    }

    private Page<SysHealthRecordDTO> convert(Page<SysHealthRecord> healthRecordPage, Pageable pageable) {
        List<SysHealthRecordDTO> healthRecordDTOList = healthRecordPage.getContent().stream()
                .map(this::convert).collect(Collectors.toList());
        return new PageImpl<>(healthRecordDTOList, pageable, healthRecordPage.getTotalElements());
    }

    private SysHealthRecord updateInfo(SysHealthRecordDTO newRecord) {
        if (newRecord == null) return null;
        if (newRecord.getRecordId() == null) return null;
        SysHealthRecord originHealthRecord = repository.findById(newRecord.getRecordId()).orElse(null);
        if (originHealthRecord == null) return null;

        //插入出入记录成功后，更新住户状态信息
        SysHealthStatus healthStatus = healthStatusService.findByUserId(newRecord.getUserId());
        if (!newRecord.getHealthStatus().equals(originHealthRecord.getHealthStatus()))
            healthStatus.setHealthStatus(newRecord.getHealthStatus());
        if (!newRecord.getTemperature().equals(originHealthRecord.getTemperature()))
            healthStatus.setTemperature(newRecord.getTemperature());

        //如果允许出入，则出入次数加1
        if (newRecord.getPassResult().equals(PassResultEnum.ALLOW.getCode())) {
            healthStatus.setAccessTimes(healthStatus.getAccessTimes() + 1);
        }else {
            healthStatus.setAccessTimes(healthStatus.getAccessTimes() - 1);
        }
        healthStatusService.save(healthStatus);

        UpdateUtil.copyNullProperties(newRecord, originHealthRecord);
        return originHealthRecord;
    }
}
